package com.javasea.spring.proxy.cglibproxy2;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class SpiFactoryBean<T> implements FactoryBean<T> {
    private Class<? extends ISpi> spiClz;

    private List<ISpi> list;

    /**
     * 遍历全部的SPI实现，根据传入的第一个参数做为条件进行匹配，找出首个命中的SPI实现类，执行 将上面的步骤具体实现
     * @param applicationContext
     * @param clz
     */
    public SpiFactoryBean(ApplicationContext applicationContext, Class<? extends ISpi> clz) {
        this.spiClz = clz;
        Map<String, ? extends ISpi> map = applicationContext.getBeansOfType(spiClz);
        list = new ArrayList<>(map.values());
        list.sort(Comparator.comparingInt(ISpi::order));
    }

    /**
     * 获取到代理对象
     * @return
     */
    @Override
    public T getObject() {
        // 动态代理执行类
        InvocationHandler invocationHandler = (proxy, method, args) -> {
            for (ISpi spi : list) {
                if (spi.verify(args[0])) {
                    // 第一个参数作为条件选择
                    return method.invoke(spi, args);
                }
            }

            throw new Exception("no spi server can execute! spiList: " + list);
        };
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{spiClz},
                invocationHandler);
    }

    @Override
    public Class<?> getObjectType() {
        return spiClz;
    }
}
